/**
 * @author lulongwen
 * Date: 2023-09-13 22:30
 * Description: ContextMenu 右键菜单
 * e.clientX 需要减去 侧边栏 192px +  padding 24
 * e.clientY 需要减去 Header 48px + Title 60px
 */

import React, { useCallback, useRef, useState } from 'react';
import ReactFlow, { Background, useNodesState, useEdgesState, addEdge } from 'reactflow';
import type { Connection, Node } from 'reactflow';
import { omitBy, isBoolean } from 'lodash-es';

import { initialNodes, initialEdges } from './nodes-edges';
import ContextMenu from './ContextMenu';

const MIN_HEIGHT = 200;
const disX = 192 + 24;
const disY = 48 + 60;

const Flow: React.FC = () => {
  const [nodes, , onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

  const [menu, setMenu] = useState<any>(null);
  const ref = useRef<HTMLDivElement | null>(null);

  const onConnect = useCallback((params: Connection) => setEdges((els) => addEdge(params, els)), [setEdges]);

  const onNodeContextMenu = useCallback(
    (event: React.MouseEvent, node: Node) => {
      // 阻止默认的右键菜单
      event.preventDefault();
      if (!ref.current) return;

      /**
       * 计算 Contextmenu 的定位
       * pane 画布的位置
       */
      const pane = ref.current.getBoundingClientRect();

      const { clientX, clientY } = event;
      const areaWidth = pane.width - MIN_HEIGHT;
      const areaHeight = pane.height - MIN_HEIGHT;

      const menuPosition = {
        id: node.id,
        top: clientY < areaHeight && clientY - disY,
        left: clientX < areaWidth && clientX - disX,
        right: clientX >= areaWidth && pane.width - clientX + disX,
        bottom: clientY >= areaHeight && pane.height - clientY + disY,
      };

      // 过滤掉 false布尔值
      const position = omitBy(menuPosition, isBoolean);
      console.log('pane', { node, menuPosition, event, position });
      setMenu(position);
    },
    [setMenu],
  );

  // Close the context menu if it's open whenever the window is clicked.
  const onPaneClick = useCallback(() => setMenu(null), [setMenu]);

  return (
    <ReactFlow
      ref={ref}
      nodes={nodes}
      edges={edges}
      onNodesChange={onNodesChange}
      onEdgesChange={onEdgesChange}
      onConnect={onConnect}
      onPaneClick={onPaneClick}
      onNodeContextMenu={onNodeContextMenu}
      // fitView
    >
      <Background />
      {menu && <ContextMenu onClick={onPaneClick} {...menu} />}
    </ReactFlow>
  );
};

export default Flow;
